
#include "LPC43xx.h"

#define COUNT_OF(a) (sizeof(a)/sizeof(a[0]))
#define USE_RMII

/* Crystal frequency into device */
#define CRYSTAL_MAIN_FREQ_IN 12000000

/* Crystal frequency into device for RTC/32K input */
#define CRYSTAL_32K_FREQ_IN 32768

uint32_t SystemCoreClock = 120000000;

/* Structure for initial base clock states */
struct CLK_BASE_STATES {
    CGU_BASE_CLK_T clk; /* Base clock */
    CGU_CLKIN_T clkin;  /* Base clock source */
    uint8_t powerdn;    /* Set to 1 if base clock is initially powered down */
};

/* Initial base clock states are mostly on */
static const struct CLK_BASE_STATES clock_states[] = {
    //{CLK_BASE_SAFE, CLKIN_IRC, 1},
    {CLK_BASE_APB1, CLKIN_MAINPLL, 0},
    {CLK_BASE_APB3, CLKIN_MAINPLL, 0},
    //{CLK_BASE_USB0, CLKIN_USBPLL, 1},
    { CLK_BASE_RESERVED1, CLKIN_MAINPLL, 0},
    //{CLK_BASE_SPI, CLKIN_MAINPLL, 0},
    //{ CLK_BASE_SPIFI, CLKIN_MAINPLL, 1},
    {CLK_BASE_PHY_TX, CLKIN_ENET_TX, 0},
#if defined(USE_RMII)
    {CLK_BASE_PHY_RX, CLKIN_ENET_TX, 0},
#else
    {CLK_BASE_PHY_RX, CLKIN_ENET_RX, 0},
#endif
    //{CLK_BASE_SDIO, CLKIN_MAINPLL, 1},
    //{CLK_BASE_SSP0, CLKIN_IDIVC, 1},
    //{CLK_BASE_SSP1, CLKIN_IDIVC, 1},
    {CLK_BASE_UART0, CLKIN_MAINPLL, 0},
    {CLK_BASE_UART1, CLKIN_MAINPLL, 0},
    {CLK_BASE_UART2, CLKIN_MAINPLL, 0},
    {CLK_BASE_UART3, CLKIN_MAINPLL, 0},
    //{CLK_BASE_OUT, CLKINPUT_PD, 1},
    //{CLK_BASE_APLL, CLKINPUT_PD, 1},
    //{CLK_BASE_CGU_OUT0, CLKINPUT_PD, 1},
    //{CLK_BASE_CGU_OUT1, CLKINPUT_PD, 1},

    /* Clocks derived from dividers */
    //{CLK_BASE_LCD, CLKIN_IDIVC, 1},
    //{CLK_BASE_USB1, CLKIN_IDIVD, 1}
};

/* Local functions */
static uint32_t SystemGetMainPLLHz(void);

void CCU1_EnableEntity(CCU_CLK_T ClockEntity, int NewState){
    if (NewState){
        LPC_CCU1->CLKCCU[ClockEntity].CFG = 1;
    } else{
        LPC_CCU1->CLKCCU[ClockEntity].CFG |= 2;
        LPC_CCU1->CLKCCU[ClockEntity].CFG &= ~(0x1);
    }
}
void CCU2_EnableEntity(CCU_CLK_T ClockEntity, int NewState){
    if (ClockEntity >= CLK_CCU2_START){
        if (NewState){
            LPC_CCU2->CLKCCU[ClockEntity - CLK_CCU2_START].CFG = 1;
        } else{
            LPC_CCU2->CLKCCU[ClockEntity - CLK_CCU2_START].CFG |= 2;
            LPC_CCU2->CLKCCU[ClockEntity - CLK_CCU2_START].CFG &= ~(0x1);
        }
    }
}
void RGU_SoftReset(RGU_RST_T ResetSignal){
    if (ResetSignal < 32){
        LPC_RGU->RESET_CTRL0 = 1 << ResetSignal;
        LPC_RGU->RESET_CTRL0 = 0;
    } else{
        LPC_RGU->RESET_CTRL1 = 1 << (ResetSignal - 32);
        LPC_RGU->RESET_CTRL1 = 0;
    }
}
int RGU_GetSignalStatus(RGU_RST_T ResetSignal){
    if (ResetSignal < 32)
        return !(LPC_RGU->RESET_ACTIVE_STATUS0 | (1 << ResetSignal));
    else
        return !(LPC_RGU->RESET_ACTIVE_STATUS1 | (1 << (ResetSignal - 32)));
}

/*
 * SystemInit() - Initialize the system
 */
void SystemInit(void)
{
	int i;

    extern void *__Vectors;
    SCB->VTOR = (unsigned int) &__Vectors;


    /* Connect base clocks */
    for (i = 0; i < COUNT_OF(clock_states); i++) {
        LPC_CGU->BASE_CLK[clock_states[i].clk] =
                         ( clock_states[i].powerdn << 0)
                         | (1 << 11) | (clock_states[i].clkin << 24);
    }
    SystemCoreClockUpdate(); /* Update SystemCoreClock variable */

    LPC_CGU->BASE_CLK[CLK_BASE_UART0] &= ~(1 << 0);
    CCU1_EnableEntity(CLK_MX_UART0, 1);
    CCU2_EnableEntity(CLK_APB0_UART0, 1);
    RGU_SoftReset(RGU_UART0_RST);

    __enable_irq();
}

/*
 * SystemCoreClockUpdate() - Update SystemCoreClock variable
 */
void SystemCoreClockUpdate(void)
{
    uint32_t reg, div, rate;

    /* Get main PLL rate */
    rate = SystemGetMainPLLHz();

    /* Get clock divider */
    reg = LPC_CCU1->CLKCCU[CLK_MX_MXCORE].CFG;
    if (((reg >> 5) & 0x7) == 0) {
        div = 1;
    }
    else {
        div = 2;
    }
    rate = rate / div;

    SystemCoreClock = rate;
}

/* Returns the frequency of the main PLL */
uint32_t SystemGetMainPLLHz(void)
{
    uint32_t PLLReg = LPC_CGU->PLL1_CTRL;
    uint32_t freq = CRYSTAL_MAIN_FREQ_IN;
    uint32_t msel, nsel, psel, direct, fbsel;
    uint32_t m, n, p;
    const uint8_t ptab[] = {1, 2, 4, 8};

    msel = (PLLReg >> 16) & 0xFF;
    nsel = (PLLReg >> 12) & 0x3;
    psel = (PLLReg >> 8) & 0x3;
    direct = (PLLReg >> 7) & 0x1;
    fbsel = (PLLReg >> 6) & 0x1;

    m = msel + 1;
    n = nsel + 1;
    p = ptab[psel];

    if (direct || fbsel) {
        return m * (freq / n);
    }

    return (m / (2 * p)) * (freq / n);
}

uint32_t GetClockFreq(uint32_t clk_src){
    return SystemCoreClock;
}



































